diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 5b9b37f..6a6a62b 100644 *** a/doc/src/sgml/func.sgml --- b/doc/src/sgml/func.sgml *************** postgres=# SELECT * FROM pg_xlogfile_nam *** 13187,13192 **** --- 13187,13198 ---- pg_total_relation_size + + pg_table_size + + + pg_indexes_size + Database Object Size Functions *************** postgres=# SELECT * FROM pg_xlogfile_nam *** 13259,13270 **** pg_total_relation_size(regclass) bigint Total disk space used by the table with the specified OID or name, ! including indexes and TOAST data --- 13265,13297 ---- + pg_table_size(regclass) + + bigint + + Total disk space with TOAST used by the table with the specified OID or name + without user defined indexes. This also includes the size of free space maps + and visibility maps attached to a table. + + + + + pg_indexes_size(regclass) + + bigint + + Total disk space used by user defined indexes attached to the table with the + specified OID or name. + + + + pg_total_relation_size(regclass) bigint Total disk space used by the table with the specified OID or name, ! including indexes and TOAST data. *************** postgres=# SELECT * FROM pg_xlogfile_nam *** 13291,13297 **** Free Space Map (see ) associated with the relation. Specifying 'vm' returns the size of the Visibility Map (see ) associated with the ! relation. --- 13318,13331 ---- Free Space Map (see ) associated with the relation. Specifying 'vm' returns the size of the Visibility Map (see ) associated with the ! relation. The total storage consumed by a table with all attached ! forks and TOAST data can be retrieved by pg_table_size. ! ! ! ! pg_indexes_size accepts the OID or name of a table and ! returns the total disk size of all user defined indexes or keys of ! the given table. *************** postgres=# SELECT * FROM pg_xlogfile_nam *** 13303,13309 **** pg_total_relation_size accepts the OID or name of a table or toast table, and returns the size in bytes of the data ! and all associated indexes and toast tables. --- 13337,13345 ---- pg_total_relation_size accepts the OID or name of a table or toast table, and returns the size in bytes of the data ! and all associated indexes and toast tables. This function ! is a shorthand version of pg_table_size ! + pg_indexes_size. diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index a280ff8..8d45992 100644 *** a/src/backend/utils/adt/dbsize.c --- b/src/backend/utils/adt/dbsize.c *************** pg_relation_size(PG_FUNCTION_ARGS) *** 302,355 **** PG_RETURN_INT64(size); } /* ! * Compute the on-disk size of files for the relation according to the ! * stat function, including heap data, index data, and toast data. */ static int64 ! calculate_total_relation_size(Oid Relid) { ! Relation heapRel; ! Oid toastOid; ! int64 size; ! ListCell *cell; ! ForkNumber forkNum; ! ! heapRel = relation_open(Relid, AccessShareLock); ! toastOid = heapRel->rd_rel->reltoastrelid; - /* Get the heap size */ size = 0; for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) ! size += calculate_relation_size(&(heapRel->rd_node), forkNum); ! /* Include any dependent indexes */ ! if (heapRel->rd_rel->relhasindex) { ! List *index_oids = RelationGetIndexList(heapRel); foreach(cell, index_oids) { Oid idxOid = lfirst_oid(cell); ! Relation iRel; ! ! iRel = relation_open(idxOid, AccessShareLock); ! for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) ! size += calculate_relation_size(&(iRel->rd_node), forkNum); ! ! relation_close(iRel, AccessShareLock); } list_free(index_oids); } ! /* Recursively include toast table (and index) size */ ! if (OidIsValid(toastOid)) ! size += calculate_total_relation_size(toastOid); ! relation_close(heapRel, AccessShareLock); return size; } --- 302,437 ---- PG_RETURN_INT64(size); } + static int64 + calculate_toast_table_size(Oid toastrelid) + { + Relation toastRel; + Relation toastIdxRel; + ForkNumber forkNum; + int64 size; + + size = 0; + toastRel = relation_open(toastrelid, AccessShareLock); + + /* toast heap size, including FSM and VM size */ + for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + size += calculate_relation_size(&(toastRel->rd_node), forkNum); + + /* toast index size, including FSM and VM size */ + toastIdxRel = relation_open(toastRel->rd_rel->reltoastidxid, AccessShareLock); + for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) + size += calculate_relation_size(&(toastIdxRel->rd_node), forkNum); + + relation_close(toastRel, AccessShareLock); + relation_close(toastIdxRel, AccessShareLock); + + PG_RETURN_INT64(size); + } /* ! * Calculates the size of a given table, ! * including TOAST table and its index, FSM ! * and VM. */ static int64 ! calculate_table_size(Oid relOid) { ! Relation rel; ! ForkNumber forkNum; ! int64 size; size = 0; + rel = relation_open(relOid, AccessShareLock); + + /* + * heap size, including FSM and VM + */ for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) ! size += calculate_relation_size(&(rel->rd_node), forkNum); ! /* ! * Size of toast relation ! */ ! if (OidIsValid(rel->rd_rel->reltoastrelid)) { ! size += calculate_toast_table_size(rel->rd_rel->reltoastrelid); ! } ! ! relation_close(rel, AccessShareLock); ! PG_RETURN_INT64(size); ! } ! ! static int64 ! calculate_indexes_size(Oid relOid) ! { ! Relation rel; ! int64 size; ! ! size = 0; ! rel = relation_open(relOid, AccessShareLock); ! ! /* ! * Aggregate all indexes on the given relation ! */ ! if (rel->rd_rel->relhasindex) { ! List *index_oids = RelationGetIndexList(rel); ! ListCell *cell; foreach(cell, index_oids) { Oid idxOid = lfirst_oid(cell); ! Relation idxRel; ! ForkNumber forkNum; ! ! idxRel = relation_open(idxOid, AccessShareLock); ! for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++) ! size += calculate_relation_size(&(idxRel->rd_node), forkNum); ! ! relation_close(idxRel, AccessShareLock); } list_free(index_oids); } + + relation_close(rel, AccessShareLock); + PG_RETURN_INT64(size); + } ! Datum ! pg_table_size(PG_FUNCTION_ARGS) ! { ! Oid relOid = PG_GETARG_OID(0); ! PG_RETURN_INT64(calculate_table_size(relOid)); ! } ! Datum ! pg_indexes_size(PG_FUNCTION_ARGS) ! { ! Oid relOid = PG_GETARG_OID(0); ! PG_RETURN_INT64(calculate_indexes_size(relOid)); ! } ! ! /* ! * Compute the on-disk size of files for the relation according to the ! * stat function, including heap data, index data, and toast data. ! */ ! static int64 ! calculate_total_relation_size(Oid Relid) ! { ! int64 size; ! ! /* ! * Aggregate the table size, this includes size of ! * the heap, toast and toast index with free space ! * and visibility map ! */ ! size = calculate_table_size(Relid); ! ! /* ! * Get size of all attached indexes as well ! */ ! size += calculate_indexes_size(Relid); return size; } diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index a8efed9..756b659 100644 *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** DATA(insert OID = 2286 ( pg_total_relati *** 3702,3707 **** --- 3702,3711 ---- DESCR("total disk space usage for the specified table and associated indexes and toast tables"); DATA(insert OID = 2288 ( pg_size_pretty PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "20" _null_ _null_ _null_ _null_ pg_size_pretty _null_ _null_ _null_ )); DESCR("convert a long int to a human readable text using size units"); + DATA(insert OID = 2997 ( pg_table_size PGNSP PGUID 12 1 0 0 f f f t f v 1 0 20 "2205" _null_ _null_ _null_ _null_ pg_table_size _null_ _null_ _null_ )); + DESCR("disk space usage including TOAST, free space and visibility map for the specified table"); + DATA(insert OID = 2998 ( pg_indexes_size PGNSP PGUID 12 1 0 0 f f f t f v 1 0 20 "2205" _null_ _null_ _null_ _null_ pg_indexes_size _null_ _null_ _null_ )); + DESCR("disk space usage of all indexes attached to the specified table"); DATA(insert OID = 2316 ( postgresql_fdw_validator PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "1009 26" _null_ _null_ _null_ _null_ postgresql_fdw_validator _null_ _null_ _null_)); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 91411a4..72e9ed0 100644 *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** extern Datum pg_database_size_name(PG_FU *** 433,438 **** --- 433,440 ---- extern Datum pg_relation_size(PG_FUNCTION_ARGS); extern Datum pg_total_relation_size(PG_FUNCTION_ARGS); extern Datum pg_size_pretty(PG_FUNCTION_ARGS); + extern Datum pg_table_size(PG_FUNCTION_ARGS); + extern Datum pg_indexes_size(PG_FUNCTION_ARGS); /* genfile.c */ extern Datum pg_stat_file(PG_FUNCTION_ARGS);